home *** CD-ROM | disk | FTP | other *** search
- # include <stdio.h>
- # include "constants.h"
- # include "globals.h"
- # include <setjmp.h>
- # include <sccs.h>
-
- SCCSID(@(#)display.c 8.1 12/31/84)
-
- /*
- ** DISPLAY.C -- display manipulation routines
- **
- ** a display is a list of strings, the symbol
- ** space Symsp is impemented by means of displays.
- **
- ** Required By:
- ** Lexical analysis routines to add to the symbol space
- ** semantic productions to manipulate input
- */
-
-
-
-
- /* this avoids having to specify &Cv_display in the semantic
- * routines, by making Cv_display a pointer to the pertinent
- * display structure.
- */
- struct display *Cv_display = &Displays [0];
-
- /*
- ** ENTER_DISPLAY -- enter a new string into a display
- **
- ** Parameters:
- ** disp -- display to be added to
- ** string -- string to add
- **
- ** Returns:
- ** pointer to new disp_node structure.
- **
- ** Side Effects:
- ** allocates a new disp_node structispl
- ** Expects a dynamic "string", i.e. one that it can
- ** dispose of as it wishes, so it is the users responsability
- ** to allocate space for this string.
- ** If the string passed is 0, the string
- ** "ERROR_TOKEN" is substituted, and a message is printed,
- ** so a caller may call enter_display with the return of an
- ** salloc() directly.
- ** If no space is available for the allocation of the
- ** new node, an error message is given, and a reset(III)
- ** is performed (this should goto equel()[main.c])
- **
- ** Called By:
- ** add_sym() -- to add a token to the Symsp
- ** the semantic productions -- for manipulating usages
- ** of C variables.
- */
-
-
- struct disp_node *enter_display(disp, string)
- struct display *disp;
- char *string;
- {
- register struct display *d;
- register struct disp_node *node;
- extern jmp_buf Jmpbuf;
-
- node = (struct disp_node *)nalloc(sizeof *node);
- if (node == 0)
- {
- yysemerr("symbol space overflow", string);
- longjmp(Jmpbuf,1);
- }
- d = disp;
- if (!d->disp_first)
- d->disp_first = d->disp_last = node;
- else
- {
- d->disp_last->d_next = node;
- d->disp_last = node;
- }
- node->d_next = 0;
- if (!(node->d_elm = string))
- {
- yysemerr("alloc error in display", 0);
- node->d_elm = "ERROR_TOKEN";
- }
- return (node);
- }
-
- /*
- ** ADDSYM -- add a token to the symbol space
- **
- ** The node's .d_line field is set to the value of yyline,
- ** which, if this routine is called from a lexical routine
- ** taking lexemes that can't include newlines (and back them up),
- ** is the line the lexeme was read from. This fact is used
- ** be yyserror() [yyerror.c] to report accurate line numbers
- ** for errors.
- **
- ** Parameters:
- ** s -- string to add
- **
- ** Returns:
- ** pointer to node added
- */
-
-
-
- struct disp_node *addsym(s)
- char *s;
- {
- register struct disp_node *d;
-
- d = enter_display(&Symsp, s);
- d->d_line = yyline;
- return (d);
- }
-
- /*
- ** FREE_DISPLAY -- frees all elements of a display
- **
- ** Parameters:
- ** disp -- the display to free
- */
-
-
-
-
-
- free_display(disp)
- struct display *disp;
- {
- register struct display *d;
- register struct disp_node *f, *n;
-
- d = disp;
- for (f = d->disp_first; f; f = n)
- {
- n = f->d_next;
- xfree(f->d_elm);
- xfree(f);
- }
- d->disp_first = d->disp_last = 0;
- }
-
- /*
- ** SYSMSPFREE -- Frees symbol space
- ** Symspfree frees all the symbol table, EXCEPT
- ** for the last element in it, as this is the lookahead
- ** element. That is to say, the element which forced reduction
- ** to the non-terminal program, which called on symspfree()
- **
- ** Requires:
- ** Symsp -- to free it
- **
- ** Called By:
- ** argproc()
- ** semantic routines (nonterminal "program")
- */
-
-
-
- symspfree()
- {
- register struct display *d;
- register struct disp_node *f, *n;
-
- d = &Symsp;
- for (f = d->disp_first; f && f->d_next; f = n)
- {
- n = f->d_next;
- xfree(f->d_elm);
- xfree(f);
- }
- d->disp_first = d->disp_last;
- }
-
- /*
- ** W_DISPLAY -- write out the contents of a display
- **
- ** Parameters:
- ** disp -- display to take write out
- **
- ** Side Effects:
- ** Writes onto Out_file
- ** the contents of the display,
- ** each string is comsidered a separate
- ** word to be written out(so w_raw may
- ** break a line between words).
- ** Calls are made to w_op() and w_key() so as
- ** to have the minimum number of spaces in the text.
- **
- ** Requires:
- ** w_op() -- to write out operator terminated
- ** strings
- ** w_key() -- to write out KEYCHAR terminated
- ** strings
- **
- ** Called By:
- ** semantic productions dealing with usage of
- ** C variables.
- */
-
-
-
- w_display(disp)
- struct display *disp;
- {
- register struct disp_node *n;
-
- for (n = disp->disp_first; n; n = n->d_next)
- {
- switch (Cmap [n->d_elm [length(n->d_elm) - 1]])
- {
-
- case OPATR :
- case PUNCT :
- w_op(n->d_elm);
- break;
-
- default :
- w_key(n->d_elm);
- break;
- }
- }
- }
- /*
- ** EAT_DISPLAY -- enter text from In_file into a display
- ** Enters all text gotten through getch() [getch.c]
- ** lying between one character delimiters, which may
- ** be nested, into a display or w_op()'s it.
- ** eat_display() assumes that when it is called a
- ** "left_ch" has just been seen. It will "eat" up to
- ** MAXSTRING characters.
- ** Newline is played with because :
- ** a) a newline may have been read by eat_display
- ** instead of yylex(), therefore if eat_display
- ** stops there, yylex() must know that a newline
- ** has just been seen and it must test for C_CODE.
- ** b) Newline may have to be set to 0 if an include()
- ** was done which sets it to 1, and no yylex() was
- ** done afterwards to reset it.
- **
- ** NOTE : This playing with Newline is needed because
- ** yylex() and not getch() maintains Newline. If getch()
- ** maintained Newline then it would be automatically right.
- **
- ** Parameters:
- ** disp -- display to add elements to if != 0 else
- ** characters are written out.
- ** left_ch -- left delimiter character
- ** right_ch -- right delimiter character
- **
- ** Side Effects:
- ** advances input to after the close of the
- ** left_ch, right_ch pair.
- ** may back up 2 characters.
- **
- ** Called By:
- ** semantic routines dealing with array subscription
- **
- ** Bugs:
- ** #include's encountered, are treated wrongly
- ** because the "#include ...c.h" is put out immediately,
- ** while the display is put out only later.
- */
-
-
- eat_display(disp, left_ch, right_ch)
- struct display *disp;
- char left_ch;
- char right_ch;
- {
- char buf [MAXSTRING + 1];
- register char *cp;
- register level;
- register i;
- char pk;
- char r_c [2];
-
- cp = buf;
- level = i = 1;
- *cp = left_ch;
- do
- {
- i++;
- if (i >= sizeof buf)
- {
- yysemerr("display too long", 0);
- break;
- }
- if ((*++cp = getch()) == left_ch)
- level++;
- else if (*cp == right_ch)
- level -= 1;
- else if (*cp == EOF_TOK)
- {
- backup(*cp);
- missing :
- r_c [1] = '\0';
- r_c [0] = right_ch;
- yysemerr("missing closing character", r_c);
- *cp = right_ch;
- /* make next line be read as possible
- * C_CODE by yylex() [yylex.c]
- */
- Newline = 1;
- break;
- }
- else if (*cp == '\n')
- {
- /* test that next line is valid equel line,
- * and strip "##"
- */
- if ((pk = getch()) != '#')
- {
- backup(pk);
- goto missing;
- }
- if ((pk = getch()) != '#')
- {
- backup(pk);
- backup('#');
- goto missing;
- }
- }
- } while (*cp != right_ch || level > 0);
- if (level == 0)
- Newline = 0;
- *++cp = '\0';
- if (disp)
- enter_display(disp, salloc(buf));
- else
- w_op(buf);
- }
-